<?php

namespace App\Models\User;

use App\Libraries\Easemob\Easemob;
use App\Libraries\Tools\CheckAuth;
use App\Libraries\Tools\ConstVar;
use App\Models\BaseModel;
use App\Models\HongBao\HongBao;
use App\Models\Shop\Shop;
use Illuminate\Auth\Authenticatable;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Laravel\Lumen\Auth\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Laravel\Passport\HasApiTokens;

class User extends BaseModel implements AuthenticatableContract, AuthorizableContract
{
    use Authenticatable, Authorizable, HasApiTokens;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'nickname',
        'email',
        'open_id',
        'x_open_id',
        'true_name',
        'sex',
        'address_id',
        'mobile',
        'is_auth',
        'vip_level',
        'vip_validity',
        'balance',
        'reg_ip',
        'is_guest',
        'is_agent',
        'guest_id',
        'district_id',
        'longitude',
        'latitude',
        'agent_city_id',
    ];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = [
        'created_at',
        'updated_at',
        'password',
        'payment_pw',
        'reg_ip',
        'open_id',
        'x_open_id',
        'remarks',
        'is_bot'
    ];

    protected $primaryKey = 'user_id';
    protected $dateFormat = 'U';

    /**
     * Passport 验证方法
     * @param $params
     * @return null
     */
    public function findForPassport($params){
        if($params['auth_type'] == 'guest'){
            $user = $this->where('user_id', $params['id'])->first();
        }else{
            $user = $this->getUserObjectByOpenIdOrMobile($params['id']);
        }
        if(empty($user)){
            return null;
        }elseif($user['status'] != 1){
            return null;
        }
        return $user;
    }

    /**
     * Passport 验证方法
     * @param $params
     * @return bool
     */
    public function validateForPassportPasswordGrant($params){
        switch($params['auth_type']){
            case 'sms':
                $sms = new SMS();
                $data = $sms->checkCode($params['id'], $params['key']);
                if(empty($data)){
                    return false;
                }
                $data->status = 1;
                $data->save();
                break;
            case 'password':
                $pw_lock = new UserPwLock();
                if(!password_verify($params['key'], $this->password)){
                    $user_pw_lock = $pw_lock->where('user_id', $this->user_id)->first();
                    if(empty($user_pw_lock)){
                        $pw_lock->login_pw = 1;
                        $pw_lock->user_id = $this->user_id;
                        $pw_lock->save();
                    }else{
                        $user_pw_lock->increment('login_pw');
                    }
                    return false;
                }else{
                    $pw_lock->updateOrCreate(['user_id'=>$this->user_id], ['login_pw'=>0]);
                }
                break;
            case 'third_party':
                break;
            case 'reg':
                break;
            case 'guest':
                break;
            default:
                return false;
        }
        return true;
    }

    /**
     * 根据open_id获取用户列表
     * @param array $open_ids
     * @return mixed
     */
    public function getUserListByOpenIds(array $open_ids){
        $data = $this->whereIn('open_id', $open_ids)
            ->orWhereIn('x_open_id',$open_ids)
            ->orderBy('user_id', 'asc')
            ->get()
            ->toArray();
        return $this->after($data);
    }

    public function checkNicknameExist($nickname, $mobile){
        $data = $this->where('nickname', $nickname)->where('mobile', '<>', $mobile)->first();
        if(empty($data)){
            return false;
        }
        return true;
    }

    /**
     * 根据user_id获取用户列表
     * @param array $user_ids
     * @return mixed
     */
    public function getUserListByUserId(array $user_ids){
        $data = $this->whereRaw('nickname is not null')
            ->where('status', 1)
            ->where('is_bot', 0)
            ->whereIn('user_id', $user_ids)
            ->orderBy('user_id', 'asc')
            ->get()
            ->toArray();
        return $this->after($data);
    }

    /**
     * 根据open_id或者mobile获取一个用户
     * @param $id
     * @return mixed
     */
    public function getUserByOpenIdOrMobile($id){
        $data = $this->getUserObjectByOpenIdOrMobile($id);
        return $this->after($data);
    }

    /**
     * 根据open_id或者mobile获取一个用户对象
     * @param $id
     * @param bool $need_shop_list
     * @param bool $need_point
     * @return User
     */
    public function getUserObjectByOpenIdOrMobile($id, $need_shop_list=false, $need_point=false){
        $sql = $this->where('open_id', $id)->orWhere('x_open_id', $id)->orWhere('mobile', $id);
        if($need_shop_list){
            $sql = $sql->withOnly('shops', ['user_id', 'title', 'shop_id', 'level']);
        }
        if($need_point){
            $sql = $sql->with('points');
        }
        $data = $sql->first();
        return $data;
    }

    /**
     * 用户列表
     * @param Request $request
     * @param $no_need_friends
     * @return mixed
     */
    public function getList(Request $request, $no_need_friends){
        $data = [];
        $not_in_id = [3,4,5,6];
        if($no_need_friends){
            $friends = Easemob::singleton()->showFriends(Auth::id());
            if(!isset($friends['error']) && is_array($friends['data'])){
                $not_in_id = array_merge($not_in_id, $friends['data']);
            }
        }
        $sql = $this->with('points')->where('status', 1)->whereNotIn('user_id', $not_in_id)->where('is_bot', 0)->where('is_guest', 0);
        switch($request['type']){
            case 1://关键字搜索
                $sql = $sql->whereRaw('(INSTR(nickname, ?) OR INSTR(mobile, ?))', [$request['keyword'], $request['keyword']]);
                break;
            case 2://同城好友
                $sql = $sql->where('vip_level', 2)
                    ->whereIn('district_id', $request['districts'])
                    ->where('user_id', '<>', Auth::id());
                break;
            default:
                break;
        }
        $data['list'] = $sql->forPage($request['page'], $request['size']+1)
            ->orderBy('user_id', 'desc')
            ->get()
            ->toArray();
        $data['next_page'] = $request['page'] + 1;
        $data['page_size'] = $request['size'];
        return $this->after($data);
    }

    /**
     * 添加VIP
     * @param $user_id
     * @param $level
     * @param $validity
     * @return bool
     */
    public function addVIP($user_id, $level, $validity){
        $time = time();
        $user = $this->where('user_id', $user_id)->firstOrFail();
        if($user->vip_validity >= $time){
            $user->vip_validity = $user->vip_validity + $validity;
        }else{
            $user->vip_validity = $time + $validity;
        }
        $user->vip_level = $level;
        $user->save();
        return true;
    }

    /**
     * transfer 前的检查
     * @param Request $request
     * @param Shop|null $shop
     * @return array
     */
    public function beforeCheck(Request $request, Shop $shop=null){
        switch($request['type']){//3-transfer_to_shop 5-transfer_to_user 6-hongbao
            case ConstVar::$ORDER_TYPE_TRANSFER_TO_SHOP:
                if(!$shop->checkIfActive($request['id'])){
                    $this->rs_format['code'] = 40001;
                    return $this->rs_format;
                }
                if(!empty($request['hong_bao_id'])){
                    $hong_bao = HongBao::where('id', $request['hong_bao_id'])
                        ->where('status', 0)
                        ->where('type', ConstVar::$HONGBAO_TYPE_CASH)
                        ->where('end_at', '>=', time())
                        ->where('limit_money', '<=', $request['transfer_amount'])
                        ->where('shop_id', $request['id'])
                        ->first();
                    if(empty($hong_bao)){
                        $this->rs_format['code'] = 40400;
                        return $this->rs_format;
                    }
                    if($hong_bao->money >= $request['transfer_amount']){
                        $this->rs_format['code'] = 40001;
                        return $this->rs_format;
                    }
                    $hong_bao->status = 1;
                    $hong_bao->save();
                }
                $this->rs_format['data']['price'] = $request['transfer_amount'];
                $this->rs_format['data']['body'] = '扫码支付';
                $this->rs_format['data']['ext_id'] = 0;
                $this->rs_format['data']['hong_bao_id'] = $request['hong_bao_id']??0;
                $this->rs_format['data']['hong_bao_amount'] = $hong_bao->money??0;
                return $this->rs_format;
                break;
            case ConstVar::$ORDER_TYPE_TRANSFER_TO_USER:
                if(!CheckAuth::checkIfValidUser($request['id'])){
                    $this->rs_format['code'] = 40001;
                    return $this->rs_format;
                }
                $this->rs_format['data']['price'] = $request['transfer_amount'];
                $this->rs_format['data']['body'] = '转账';
                $this->rs_format['data']['ext_id'] = 0;
                $this->rs_format['data']['hong_bao_id'] = 0;
                $this->rs_format['data']['hong_bao_amount'] = 0;
                return $this->rs_format;
                break;
            case ConstVar::$ORDER_TYPE_HONGBAO:
                $this->rs_format['code'] = 50001;
                return $this->rs_format;
                break;
            default:
                $this->rs_format['code'] = 50001;
                return $this->rs_format;
                break;
        }
    }

    /**
     * 关联商家
     * @return mixed
     */
    public function shops(){
        return $this->hasMany('App\Models\Shop\ShopManagerFullDetail', 'user_id', 'user_id')
            ->where('status', 1)
            ->where('shop_status', 1)
            ->where('verify_status', 1);
    }

    /**
     * 关联积分
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function points(){
        return $this->hasOne('App\Models\User\UserPoint', 'user_id', 'user_id');
    }
}
